<template>
  <div class="face-verify-container">
    <header class="header">
      <div class="logo-container">
        <img src="../../assets/logo.png" alt="Logo" class="logo">
        <h1>排队叫号系统</h1>
      </div>
      <div class="time">{{ currentTime }}</div>
    </header>

    <div class="content">
      <div class="welcome-section">
        <h2>人脸验证</h2>
        <p class="subtitle">请点击按钮开始人脸验证</p>
      </div>

      <div class="verify-section">
        <el-card shadow="hover" class="verify-card">
          <div class="ticket-info">
            <h3>当前叫号</h3>
            <div class="ticket-number">{{ verifyForm.ticketNumber || '等待叫号...' }}</div>
            <p class="ticket-status">{{ ticketStatusText }}</p>
          </div>

          <div class="waiting-section" v-if="!verifyForm.ticketNumber && !verificationStarted">
            <el-alert
              title="等待叫号中..."
              type="info"
              :closable="false"
              description="请等待工作人员叫号"
              show-icon
            />
          </div>

          <div class="input-section" v-if="verifyForm.ticketNumber && !verificationStarted && !verificationCompleted">
            <el-button
              type="primary"
              @click="startVerification"
              size="large"
              class="verify-button"
            >
              开始人脸验证
            </el-button>
          </div>

          <div class="camera-section" v-if="verificationStarted && !verificationCompleted">
            <div class="face-canvas">
              <video ref="videoRef" class="video-stream" autoplay playsinline></video>
              <canvas ref="canvasRef" class="face-canvas" style="display: none;"></canvas>

              <div class="face-overlay" :class="{ 'face-detected': faceDetected }">
                <div class="face-frame"></div>
                <div class="corner top-left"></div>
                <div class="corner top-right"></div>
                <div class="corner bottom-left"></div>
                <div class="corner bottom-right"></div>
              </div>
            </div>

            <div class="face-status">
              {{ faceStatusMessage }}
            </div>
          </div>

          <!-- 成功验证情况下显示类似截图中的界面 -->
          <div class="success-section" v-if="verificationSuccess && verificationCompleted">
            <div class="result-icon success">
              <el-icon><CircleCheck /></el-icon>
            </div>
            <div class="result-message">
              {{ resultMessage }}
            </div>
            <div class="service-status">
              <p>服务状态：<span class="status-highlight">{{ serviceStatus }}</span></p>
              <p>请前往窗口办理业务</p>
            </div>
          </div>

          <!-- 验证失败的情况 -->
          <div class="result-section" v-if="verificationCompleted && !verificationSuccess">
            <div class="result-icon failed">
              <el-icon><CircleClose /></el-icon>
            </div>
            <div class="result-message">
              {{ resultMessage }}
            </div>
            <div class="result-actions">
              <el-button @click="retryVerification">重新验证</el-button>
            </div>
          </div>
        </el-card>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, onUnmounted, computed, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessage } from 'element-plus'
import {
  Ticket, CircleCheck, CircleClose
} from '@element-plus/icons-vue'
import axios from "axios";

const router = useRouter()
const route = useRoute()

// 当前时间
const currentTime = ref('')
let timer = null

// 表单数据和验证规则
const verifyFormRef = ref(null)
const verifyForm = reactive({
  ticketNumber: '',
  windowId: null
})
const rules = {
  ticketNumber: [
    { required: true, message: '请输入排队号码', trigger: 'blur' },
    { pattern: /^[A-Za-z]\d{3,}$/, message: '排队号码格式不正确', trigger: 'blur' }
  ]
}

// 验证状态
const verificationStarted = ref(false)
const verificationCompleted = ref(false)
const verificationSuccess = ref(false)
const resultMessage = ref('')

// 人脸识别相关
const videoRef = ref(null)
const canvasRef = ref(null)
const stream = ref(null)
const faceDetected = ref(false)
const faceStatusMessage = ref('请正视摄像头...')

// 服务状态
const serviceStatus = ref('等待验证')

// 票号状态
const ticketStatus = ref('waiting') // waiting, verifying, verified, serving
const ticketStatusText = computed(() => {
  switch (ticketStatus.value) {
    case 'waiting':
      return '等待验证';
    case 'verifying':
      return '正在验证';
    case 'verified':
      return '验证完成';
    case 'serving':
      return '正在服务中';
    default:
      return '等待验证';
  }
})

// 轮询间隔（毫秒）
const POLLING_INTERVAL = 3000
let pollingTimer = null

// 定时器ID
let faceDetectionTimer = null

// 更新当前时间
const updateTime = () => {
  const now = new Date()
  const year = now.getFullYear()
  const month = (now.getMonth() + 1).toString().padStart(2, '0')
  const date = now.getDate().toString().padStart(2, '0')
  const hours = now.getHours().toString().padStart(2, '0')
  const minutes = now.getMinutes().toString().padStart(2, '0')
  const seconds = now.getSeconds().toString().padStart(2, '0')
  const day = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'][now.getDay()]

  currentTime.value = `${year}年${month}月${date}日 ${hours}:${minutes}:${seconds} ${day}`
}

// 开始验证
const startVerification = () => {
  // 检查是否有票号
  if (!verifyForm.ticketNumber) {
    ElMessage.warning('无法获取当前叫号信息，请联系工作人员')
    return
  }

  verificationStarted.value = true
  verificationCompleted.value = false
  verificationSuccess.value = false
  faceDetected.value = false
  ticketStatus.value = 'verifying'

  // 初始化摄像头
  initFaceCamera()

  // 向服务器发送验证开始状态
  sendVerificationStatus('STARTED')

  // 通知叫号终端开始验证
  notifyVerificationStarted()
}

// 通知叫号终端开始验证
const notifyVerificationStarted = () => {
  try {
    if (window.opener && !window.opener.closed) {
      // 向打开此窗口的页面发送消息，表示开始验证
      window.opener.postMessage({
        type: 'FACE_VERIFICATION_STARTED',
        ticketNumber: verifyForm.ticketNumber,
        timestamp: new Date().toISOString()
      }, '*')

      console.log('已通知叫号终端开始验证:', verifyForm.ticketNumber)
    } else {
      console.log('没有找到父窗口，无法发送开始验证通知')
    }
  } catch (error) {
    console.error('向父窗口发送消息失败:', error)
  }
}

// 重试验证
const retryVerification = () => {
  resetVerification()
  // 短暂延迟后开始验证
  setTimeout(() => {
    startVerification()
  }, 500)
}

// 初始化人脸摄像头
const initFaceCamera = async () => {
  try {
    // 如果已有流，先关闭
    if (stream.value) {
      stopCamera()
    }

    // 重置人脸检测状态
    faceDetected.value = false
    faceStatusMessage.value = '请正视摄像头...'

    // 获取摄像头流
    stream.value = await navigator.mediaDevices.getUserMedia({
      video: {
        width: 320,
        height: 240,
        facingMode: 'user'
      }
    })

    // 设置视频源
    if (videoRef.value) {
      videoRef.value.srcObject = stream.value
      videoRef.value.onloadedmetadata = () => {
        // 视频准备好后开始处理视频帧
        startFaceDetection()
      }
    }
  } catch (error) {
    console.error('初始化摄像头失败:', error)
    faceStatusMessage.value = '无法访问摄像头，请检查权限设置'

    // 报告摄像头错误状态
    sendVerificationStatus('CAMERA_ERROR')
  }
}

// 开始人脸检测
const startFaceDetection = () => {
  // 清除可能存在的旧定时器
  if (faceDetectionTimer) {
    clearInterval(faceDetectionTimer)
  }

  // 设置定时器，每500毫秒处理一次视频帧
  faceDetectionTimer = setInterval(() => {
    processFaceFrame()
  }, 500)
}

// 处理视频帧进行人脸检测
const processFaceFrame = () => {
  if (!videoRef.value || !canvasRef.value || !stream.value) return

  const video = videoRef.value
  const canvas = canvasRef.value
  const context = canvas.getContext('2d')

  // 设置画布尺寸与视频一致
  canvas.width = video.videoWidth
  canvas.height = video.videoHeight

  // 绘制视频帧到画布
  context.drawImage(video, 0, 0, canvas.width, canvas.height)

  // 这里实际项目中应该调用人脸检测API，现在使用模拟数据
  // 在真实环境中，可以将canvas的数据转为blob后发送到后端进行人脸验证

  // 模拟人脸检测和验证过程
  const detected = Math.random() > 0.3

  if (detected && !faceDetected.value) {
    console.log('检测到人脸')
    faceDetected.value = true
    faceStatusMessage.value = '人脸已检测到，正在验证身份...'

    // 向服务器发送人脸检测状态
    sendVerificationStatus('FACE_DETECTED')

    // 真实项目中，这里应该停止连续检测，并发送人脸特征数据到后端验证
    clearInterval(faceDetectionTimer)

    // 模拟与后端验证的过程
    setTimeout(() => {
      const verifySuccess = true;
      completeVerification(verifySuccess)
    }, 1500)
  }
}

// 完成验证
const completeVerification = (success) => {
  verificationCompleted.value = true
  verificationSuccess.value = success
  ticketStatus.value = success ? 'verified' : 'waiting'

  if (success) {
    // 验证成功，自动通知叫号终端并准备下一个验证
    resultMessage.value = `验证成功，已自动开始服务。号码: ${verifyForm.ticketNumber}`
    serviceStatus.value = '服务中'

    // 停止摄像头 - 验证成功后不再显示摄像头画面
    stopCamera()

    // 向服务器发送验证结果状态
    sendVerificationStatus(success ? 'VERIFIED_SUCCESS' : 'VERIFIED_FAILED')

    // 延迟2秒后隐藏验证页面的视频界面，只显示成功结果
    setTimeout(() => {
      // 页面会保持显示验证成功的状态
      console.log('验证已完成，结果页面将保持显示')
    }, 2000)
  } else {
    resultMessage.value = '验证失败，人脸信息与排队记录不匹配，请重试或联系工作人员'
    serviceStatus.value = '验证失败'

    // 停止摄像头
    stopCamera()

    // 向服务器发送验证结果状态
    sendVerificationStatus('VERIFIED_FAILED')

  }
}


// 向服务器发送验证状态（模拟）
const sendVerificationStatus = (status) => {
  // 实际项目中这里应该是一个API调用，向后端发送状态
  console.log(`向后端发送验证状态: ${status}, 票号: ${verifyForm.ticketNumber}`)

  // API调用
  if ('STARTED' === status) {
    axios.get('/callTerminal/startService', {
      params: {
        ticketNumber: verifyForm.ticketNumber,
        windowId: verifyForm.windowId,
      }
    }).then(() => {
      ElMessage.success('开始服务')
      notifyParentWindow(true);
      setTimeout(()=> {
        window.close()
      }, 5000)
    });
  }
}

// 通知父窗口验证结果
const notifyParentWindow = (success) => {
  // 尝试向父窗口或打开此窗口的窗口发送消息
  try {
    if (window.opener && !window.opener.closed) {
      // 如果是由另一个窗口打开的，向打开的窗口发送消息
      window.opener.postMessage({
        type: 'FACE_VERIFICATION_RESULT',
        success,
        ticketNumber: verifyForm.ticketNumber,
        timestamp: new Date().toISOString()
      }, '*')
      console.log('向父窗口发送验证结果:', success)
    }
  } catch (error) {
    console.error('向父窗口发送消息失败:', error)
  }
}

// 重置验证
const resetVerification = () => {
  verificationStarted.value = false
  verificationCompleted.value = false
  faceDetected.value = false
  ticketStatus.value = 'waiting'

  // 停止摄像头
  stopCamera()

  // 向服务器发送重置状态
  sendVerificationStatus('RESET')
}


// 停止摄像头
const stopCamera = () => {
  // 清除人脸检测定时器
  if (faceDetectionTimer) {
    clearInterval(faceDetectionTimer)
    faceDetectionTimer = null
  }

  // 停止并释放摄像头流
  if (stream.value) {
    stream.value.getTracks().forEach(track => track.stop())
    stream.value = null
  }
}


// 监听URL参数变化
watch(() => route.query.ticketNumber, (newTicketNumber) => {
  console.log("route.query.ticketNumber:" + newTicketNumber);
  if (newTicketNumber && newTicketNumber !== verifyForm.ticketNumber) {
    // 如果URL参数中的票号与当前票号不同，则更新
    verifyForm.ticketNumber = newTicketNumber
    resetVerification()
  }
}, { immediate: true })
watch(() => route.query.windowId, (value) => {
  console.log("route.query.windowId:" + value);
  if (value && value !== verifyForm.windowId) {
    // 如果URL参数中的票号与当前票号不同，则更新
    verifyForm.windowId = value
  }
}, { immediate: true })

// 监听消息事件，用于接收来自窗口操作页面的消息
const setupMessageListener = () => {
  window.addEventListener('message', (event) => {
    const data = event.data

    // 验证消息源的安全性（生产环境应更严格）

    // 处理来自终端操作页面的消息 - 设置票号
    if (data && data.type === 'SET_TICKET_NUMBER') {
      if (data.ticketNumber) {
        // 检查是否正在进行验证或已完成验证但没有处理完
        if (verificationStarted.value || (verificationCompleted.value && !verificationSuccess.value)) {
          console.log('当前有正在进行的验证，将在验证完成后处理新票号')

          // 储存新票号，待验证完成后处理
          pendingTicket.value = {
            ticketNumber: data.ticketNumber,
            windowNumber: data.windowNumber
          }
          return
        }

        // 如果当前验证已完成且成功，可以直接处理新票号
        handleTicketUpdate(data.ticketNumber, data.windowNumber)
      }
    }

    // 处理来自终端操作页面的消息 - 服务完成
    if (data && data.type === 'SERVICE_COMPLETED') {
      // 如果有票号匹配，重置页面并准备下一个验证
      if (data.ticketNumber === verifyForm.ticketNumber) {
        console.log('收到服务完成消息:', data.ticketNumber)

        // 显示服务完成消息
        ElMessage({
          message: `票号 ${data.ticketNumber} 的服务已完成`,
          type: 'success',
          duration: 3000
        })

        // 重置验证状态并准备处理下一个票号
        setTimeout(() => {
          if (pendingTicket.value) {
            // 处理待验证的票号
            const { ticketNumber, windowNumber } = pendingTicket.value
            pendingTicket.value = null
            handleTicketUpdate(ticketNumber, windowNumber)
          } else {
            // 没有待处理票号，重置页面
            resetVerification()
            verifyForm.ticketNumber = ''
          }
        }, 1000)
      }
    }
  })
}


// 添加等待处理的票号
const pendingTicket = ref(null)

// 处理票号更新
const handleTicketUpdate = (ticketNumber, windowNumber) => {
  console.log(`收到新票号: ${ticketNumber}, 窗口: ${windowNumber || '未知'}`)

  // 重置验证状态
  resetVerification()

  // 更新票号
  verifyForm.ticketNumber = ticketNumber
  verifyForm.windowId = windowNumber;

  // 如果有窗口号，更新标题
  if (windowNumber) {
    document.title = `人脸验证系统 - 窗口${windowNumber}`;
  }

  // 播放提示音通知用户
  playNotificationSound()

  // 显示通知
  ElMessage({
    message: `请验证票号: ${ticketNumber}`,
    type: 'success',
    duration: 5000
  })
}

// 播放通知提示音
const playNotificationSound = () => {
  try {
    // 创建音频上下文
    const audioContext = new (window.AudioContext || window.webkitAudioContext)()
    const oscillator = audioContext.createOscillator()
    const gainNode = audioContext.createGain()

    oscillator.connect(gainNode)
    gainNode.connect(audioContext.destination)

    // 设置提示音
    oscillator.type = 'sine'
    oscillator.frequency.value = 880
    gainNode.gain.value = 0.3

    // 播放短促提示音
    oscillator.start()

    // 500毫秒后停止
    setTimeout(() => {
      oscillator.stop()
    }, 500)
  } catch (error) {
    console.error('播放提示音失败:', error)
  }
}

// 组件挂载时
onMounted(() => {
  // 更新当前时间
  updateTime()
  timer = setInterval(updateTime, 1000)

  // 设置消息监听
  setupMessageListener()

  // 如果URL中有票号参数，自动填充
  const ticketNumber = route.query.ticketNumber
  if (ticketNumber) {
    verifyForm.ticketNumber = ticketNumber
  } else {
    // 显示欢迎信息
    ElMessage({
      message: '欢迎使用人脸验证系统，请等待叫号',
      type: 'info',
      duration: 5000
    })
  }

  // 添加窗口标题
  document.title = `人脸验证系统 - 窗口${route.query.windowNumber || ''}`;
})

// 组件卸载时
onUnmounted(() => {
  // 清除定时器
  clearInterval(timer)

  if (faceDetectionTimer) {
    clearInterval(faceDetectionTimer)
  }

  // 确保摄像头已关闭
  stopCamera()
})

</script>

<style scoped>
.face-verify-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background-color: #f6f8fc;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 20px;
  background-color: #1976d2;
  color: white;
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

.logo-container {
  display: flex;
  align-items: center;
}

.logo {
  height: 40px;
  margin-right: 15px;
}

.logo-container h1 {
  font-size: 24px;
  font-weight: bold;
}

.time {
  font-size: 18px;
}

.content {
  flex: 1;
  padding: 20px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.welcome-section {
  text-align: center;
  margin-bottom: 30px;
}

.welcome-section h2 {
  font-size: 32px;
  color: #1976d2;
  margin-bottom: 10px;
}

.subtitle {
  font-size: 18px;
  color: #616161;
}

.verify-section {
  width: 100%;
  max-width: 600px;
}

.verify-card {
  padding: 20px;
}

.ticket-info {
  text-align: center;
  margin-bottom: 20px;
  padding-bottom: 20px;
  border-bottom: 1px solid #eee;
}

.ticket-info h3 {
  font-size: 16px;
  color: #606266;
  margin-bottom: 5px;
}

.ticket-number {
  font-size: 36px;
  font-weight: bold;
  color: #1976d2;
  margin: 10px 0;
}

.ticket-status {
  font-size: 14px;
  color: #909399;
}

.waiting-section {
  margin: 20px 0;
}

.input-section {
  margin: 20px 0;
  text-align: center;
}

.ticket-input {
  width: 100%;
}

.verify-button {
  width: 80%;
  height: 50px;
  font-size: 18px;
}

.camera-section {
  margin: 20px 0;
}

.face-canvas {
  position: relative;
  width: 320px;
  height: 240px;
  margin: 15px auto;
  border-radius: 8px;
  overflow: hidden;
  background-color: #f0f0f0;
}

.video-stream {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.face-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  transition: all 0.3s ease;
}

.face-frame {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 160px;
  height: 160px;
  border-radius: 50%;
  border: 2px dashed rgba(255, 255, 255, 0.5);
}

.face-detected .face-frame {
  border: 2px solid #67C23A;
}

.corner {
  position: absolute;
  width: 20px;
  height: 20px;
  border-color: rgba(255, 255, 255, 0.8);
  border-style: solid;
  border-width: 0;
}

.top-left {
  top: 30px;
  left: 70px;
  border-top-width: 2px;
  border-left-width: 2px;
}

.top-right {
  top: 30px;
  right: 70px;
  border-top-width: 2px;
  border-right-width: 2px;
}

.bottom-left {
  bottom: 30px;
  left: 70px;
  border-bottom-width: 2px;
  border-left-width: 2px;
}

.bottom-right {
  bottom: 30px;
  right: 70px;
  border-bottom-width: 2px;
  border-right-width: 2px;
}

.face-detected .corner {
  border-color: #67C23A;
}

.face-status {
  font-size: 14px;
  color: #606266;
  margin-top: 10px;
  height: 20px;
  text-align: center;
}

.face-detected ~ .face-status {
  color: #67C23A;
}

/* 验证成功后显示的样式，类似截图 */
.detection-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 20px 0;
}

.detection-frame {
  position: relative;
  width: 320px;
  height: 320px;
  margin: 0 auto;
  background-color: #000;
  border-radius: 8px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.detection-circle {
  width: 200px;
  height: 200px;
  border-radius: 50%;
  border: 3px solid #67C23A;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

.detection-circle::before,
.detection-circle::after {
  content: '';
  position: absolute;
  width: 20px;
  height: 20px;
  border-color: #67C23A;
  border-style: solid;
}

.success-icon {
  font-size: 80px;
  color: #67C23A;
}

.detection-status {
  font-size: 16px;
  color: #606266;
  margin-top: 15px;
  text-align: center;
}

.result-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px 0;
}

.success-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 10px 0;
}

.result-icon {
  font-size: 64px;
  margin-bottom: 20px;
}

.result-icon.success {
  color: #67C23A;
}

.result-icon.failed {
  color: #F56C6C;
}

.result-message {
  font-size: 18px;
  text-align: center;
  margin-bottom: 20px;
  color: #303133;
}

.service-status {
  margin: 15px 0;
  padding: 15px;
  background-color: #f0f9eb;
  border-radius: 4px;
  width: 100%;
  text-align: center;
}

.status-highlight {
  color: #67C23A;
  font-weight: bold;
}

.result-actions {
  display: flex;
  gap: 15px;
  margin-top: 10px;
}

@keyframes pulse {
  0% { opacity: 0.7; }
  50% { opacity: 1; }
  100% { opacity: 0.7; }
}

.waiting-section .el-alert {
  animation: pulse 2s infinite;
}
</style>
